import java.io.Serializable;

/**
 * 商品基类，包含所有商品的公共属性和方法
 */
public abstract class Product implements Serializable {
    private static final long serialVersionUID = 1L;
    private String productId;      // 商品编号
    private String name;           // 商品名称
    private double price;          // 商品价格
    private String description;    // 商品描述
    private int stock;             // 库存数量

    /**
     * 构造方法
     * @param productId 商品编号
     * @param name 商品名称
     * @param price 商品价格
     * @param description 商品描述
     * @param stock 库存数量
     * @throws InvalidPriceException 当价格无效时抛出异常
     */
    public Product(String productId, String name, double price, String description, int stock) throws InvalidPriceException {
        this.productId = productId;
        this.name = name;
        setPrice(price);  // 使用setter方法进行价格验证
        this.description = description != null ? description : "";
        this.stock = Math.max(0, stock);  // 确保库存不为负数
    }

    /**
     * 获取商品编号
     * @return 商品编号
     */
    public String getProductId() {
        return productId;
    }

    /**
     * 设置商品编号
     * @param productId 商品编号
     */
    public void setProductId(String productId) {
        this.productId = productId;
    }

    /**
     * 获取商品名称
     * @return 商品名称
     */
    public String getName() {
        return name;
    }

    /**
     * 设置商品名称
     * @param name 商品名称
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取商品价格
     * @return 商品价格
     */
    public double getPrice() {
        return price;
    }

    /**
     * 设置价格，包含价格验证
     * @param price 商品价格
     * @throws InvalidPriceException 当价格小于等于0时抛出异常
     */
    public void setPrice(double price) throws InvalidPriceException {
        if (price <= 0) {
            throw new InvalidPriceException("商品价格必须大于0: " + price);
        }
        this.price = price;
    }

    /**
     * 获取商品描述
     * @return 商品描述
     */
    public String getDescription() {
        return description;
    }

    /**
     * 设置商品描述
     * @param description 商品描述，自动处理null值
     */
    public void setDescription(String description) {
        this.description = description != null ? description : "";
    }

    /**
     * 获取商品库存数量
     * @return 库存数量
     */
    public int getStock() {
        return stock;
    }

    /**
     * 设置商品库存数量
     * @param stock 库存数量，确保不为负数
     */
    public void setStock(int stock) {
        this.stock = Math.max(0, stock);  // 确保库存不为负数
    }

    /**
     * 增加库存
     * @param quantity 增加的数量
     */
    public void addStock(int quantity) {
        if (quantity > 0) {
            this.stock += quantity;
        }
    }

    /**
     * 减少库存
     * @param quantity 减少的数量
     * @return 是否成功减少库存
     */
    public boolean reduceStock(int quantity) {
        if (quantity > 0 && this.stock >= quantity) {
            this.stock -= quantity;
            return true;
        }
        return false;
    }

    /**
     * 计算折扣价格
     * @param discountRate 折扣率（0.1表示10%折扣）
     * @return 折扣后的价格
     * @throws InvalidPriceException 当折扣无效时抛出异常
     */
    public double calculateDiscountPrice(double discountRate) throws InvalidPriceException {
        if (discountRate < 0 || discountRate > 1) {
            throw new InvalidPriceException("折扣率必须在0到1之间: " + discountRate);
        }
        return price * (1 - discountRate);
    }

    /**
     * 抽象方法，由子类实现具体的商品信息展示
     * @return 商品详细信息
     */
    public abstract String getDetails();

    /**
     * 返回商品的字符串表示形式
     * @return 包含商品基本信息的字符串
     */
    @Override
    public String toString() {
        return String.format("商品编号: %s, 名称: %s, 价格: Y%.2f, 库存: %d", productId, name, price, stock);
    }
}